const data = { foo: 1, bar: 999 }
let activeEffect = null 
const bucket = new WeakMap()
let effectStack = []
const effect = (fn, options = {}) => {
    const effectFn = () => {
        clearup(effectFn)
        activeEffect = effectFn
        effectStack.push(activeEffect)
        const res = fn()
        effectStack.pop()
        activeEffect = effectStack[effectStack.length -1]
        return res 
    }
    effectFn.deps = []
    effectFn.options = options
    if (!options.lazy) {
        effectFn()
    } 
    return effectFn
    
}
const clearup = (effectFn) => {
    for (let i = 0; i < effectFn.deps.length; i++) {
        const deps = effectFn.deps[i]
        deps.delete(effectFn)
    }
    effectFn.deps.length = 0
}
const track = (target, key) => {
    let depsMap = bucket.get(target)
    if (!depsMap) bucket.set(target, depsMap = new Map())
    let deps = depsMap.get(key)
    if (!deps) depsMap.set(key, deps = new Set())
    deps.add(activeEffect)
    activeEffect.deps.push(deps)
} 
const trigger = (target, key) => {
    console.log("执行了~")
    const depsMap = bucket.get(target)
    if (!depsMap) return true
    const effects = depsMap.get(key)
    const effectsToRun = new Set()
    effects && effects.forEach(fn => {
        if (activeEffect !== fn) {
            effectsToRun.add(fn)
        }
    })
    // 找一个方法 能在foreach 里面进行 delete add 
    
    // 收集到的fn 执行  fn执行  会重新建立依赖关系 删除 添加 删除 添加
    effectsToRun && effectsToRun.forEach(effectFn => {
        // 有scheduler 就 使用 scheduler 
        if (effectFn.options && effectFn.options.scheduler) {
            effectFn.options.scheduler(effectFn)
        } else {
            effectFn()
        }
    });
}
const obj = new Proxy(data, {
    get(target, key) {
        if (!activeEffect) return target[key]
        // 追踪的核心 
        track(target, key)
        return target[key]
    },
    set(target, key, newVale) {
        target[key] = newVale
        // 触发的逻辑
        trigger(target, key)
    }   
})
// computed 会返回一个对象 该对象的value属性是一个访问属性 
// 只有读取的时候 才会执行effectFn 并且将其结果返回作为函数 
function computed(getter) {
    const effectFn = effect(getter, {
        lazy: true,
        scheduler() {
            if (!dirty) {
                dirty = true 
                console.log('scheduler, 2333')
                trigger(obj, 'value')
            }
        }
    })
    let value 
    // dirty true 需要重新计算 
    let dirty = true 
    // 读取 value的时候 才会执行effectFn
    const obj = {
        get value() {
            if (dirty) {
                value = effectFn()
                dirty = false 
            }
            // 读取value时，手动调用track函数进行追踪
            track(obj, 'value')
            return value
        }
    }
    return obj
}
// 理解流程
const sum = computed(() => obj.foo + obj.bar)
effect(() => {
    console.log(sum.value)
})
obj.foo++

// console.log('完结~')